﻿Type.registerNamespace("EcmaDoc");

/**
 * @class
 */
EcmaDoc.Toggle = function Toggle()
{
};

/**
 * Attaches the event handlers to designated page HTML elements.
 */
EcmaDoc.Toggle.setup = function Toggle$setup()
{
	EcmaDoc.Toggle.switches = $$(".toggleblock .switch");
	EcmaDoc.Toggle.masterSwitch = $(".header .controls .toggle");

	$evt.addListener(EcmaDoc.Toggle.switches, "onclick", EcmaDoc.Toggle.onBlockSwitchClick);
	$evt.addListener(EcmaDoc.Toggle.masterSwitch, "onclick", EcmaDoc.Toggle.toggleAllBlocks);
	$evt.addListener($(".controls .visibility"), "onclick", EcmaDoc.Toggle.togglePrivates);
};

/**
 * Handles the click event on a block switch element
 * @param {DOMEvent} e The event that was raised.
 */
EcmaDoc.Toggle.onBlockSwitchClick = function Toggle$onBlockSwitchClick(e)
{
	var src = $evt.srcElement(e);
	EcmaDoc.Toggle.toggleBlock(src);
};

/**
 * Toggles the visibility of a single block element.
 * @param {HTMLElement} switchElem The element that should be toggled.
 */
EcmaDoc.Toggle.toggleBlock = function Toggle$toggleBlock(switchElem)
{
	var block = EcmaDoc.Toggle.getBlockFromSwitch(switchElem);
	var detail = EcmaDoc.Toggle.getDetailFromSwitch(switchElem);
	if (!detail)
		return;

	if (detail.offsetHeight)
		EcmaDoc.Toggle.hideBlock(switchElem);
	else
		EcmaDoc.Toggle.showBlock(switchElem);

	EcmaDoc.Toggle.updateSwitches();
};

/**
 * Hides a single block element.
 * @param {HTMLElement} switchElem The element that should be hidden.
 */
EcmaDoc.Toggle.hideBlock = function Toggle$hideBlock(switchElem)
{
	var block = EcmaDoc.Toggle.getBlockFromSwitch(switchElem);
	var detail = EcmaDoc.Toggle.getDetailFromSwitch(switchElem);
	if (!detail)
		return;

	$css.addClass(block, "closed");
};

/**
 * Shows a single block element.
 * @param {HTMLElement} switchElem The element that should be shown.
 */
EcmaDoc.Toggle.showBlock = function Toggle$showBlock(switchElem)
{
	var block = EcmaDoc.Toggle.getBlockFromSwitch(switchElem);
	var detail = EcmaDoc.Toggle.getDetailFromSwitch(switchElem);
	if (!detail)
		return;

	$css.removeClass(block, "closed");
};

/**
 * Returns the container block element of the supplied switch element.
 * @param {HTMLElement} switchElem The switch element.
 */
EcmaDoc.Toggle.getBlockFromSwitch = function Toggle$getBlockFromSwitch(switchElem)
{
	return $dom.parentOrSelf(switchElem, ".toggleblock");
};

/**
 * Returns the related detail element of the supplied switch element.
 * @param {HTMLElement} switchElem The switch element.
 */
EcmaDoc.Toggle.getDetailFromSwitch = function Toggle$getDetailFromSwitch(switchElem)
{
	return $("> .toggledetail", EcmaDoc.Toggle.getBlockFromSwitch(switchElem));
};

/**
 * Toggles the visibility of all blocks on the page
 */
EcmaDoc.Toggle.toggleAllBlocks = function Toggle$toggleAllBlocks()
{
	if (EcmaDoc.Toggle.areAllBlocksHidden())
		EcmaDoc.Toggle.showAllBlocks();
	else
		EcmaDoc.Toggle.hideAllBlocks();

	EcmaDoc.Toggle.updateSwitches();
};

EcmaDoc.Toggle.togglePrivates = function Toggle$togglePrivates()
{
	if ($css.containsClass(document.body, "showPrivates"))
	{
		$css.removeClass(document.body, "showPrivates");
	}
	else
	{
		$css.addClass(document.body, "showPrivates");
	}
};

/**
 * Shows all blocks on the page
 */
EcmaDoc.Toggle.showAllBlocks = function Toggle$showAllBlocks()
{
	EcmaDoc.Toggle.switches.each(EcmaDoc.Toggle.showBlock);
};

/**
 * Hides all blocks on the page
 */
EcmaDoc.Toggle.hideAllBlocks = function Toggle$hideAllBlocks()
{
	EcmaDoc.Toggle.switches.each(EcmaDoc.Toggle.hideBlock);
};

/**
 * Returns true if all blocks on the page are hidden
 * @return {Boolean} <c>true</c> if all blocks on the page are hidden
 */
EcmaDoc.Toggle.areAllBlocksHidden = function Toggle$areAllBlocksHidden()
{
	var countHidden = 0;
	for (var i = 0; i < EcmaDoc.Toggle.switches.length; i++)
	{
		var detail = EcmaDoc.Toggle.getDetailFromSwitch(EcmaDoc.Toggle.switches[i]);
		if (!detail)
			continue;

		if (detail.offsetHeight == 0)
			countHidden++;
	}

	return countHidden == EcmaDoc.Toggle.switches.length;
};

/**
 * Updates the master switch text and persists the switch settings into a cookie.
 */
EcmaDoc.Toggle.updateSwitches = function Toggle$updateSwitches()
{
	if (EcmaDoc.Toggle.areAllBlocksHidden())
	{
		$css.display($(".expand", EcmaDoc.Toggle.masterSwitch));
		$css.undisplay($(".collapse", EcmaDoc.Toggle.masterSwitch));
	}
	else
	{
		$css.undisplay($(".expand", EcmaDoc.Toggle.masterSwitch));
		$css.display($(".collapse", EcmaDoc.Toggle.masterSwitch));
	}

	var hidden = [];
	for (var i = 0; i < EcmaDoc.Toggle.switches.length; i++)
	{
		var block = EcmaDoc.Toggle.getBlockFromSwitch(EcmaDoc.Toggle.switches[i]);
		var detail = EcmaDoc.Toggle.getDetailFromSwitch(EcmaDoc.Toggle.switches[i]);

		if (detail.offsetHeight == 0)
		{
			if (block.className.match(/toggleblock ([\w\-]+)/))
				hidden.push(RegExp.$1);
		}
	}

	$cookie.set("EcmaDoc.toggled", hidden.join(","));
};

EcmaDoc.Toggle.initializeSwitches = function Toggle$initializeSwitches()
{
	var hidden = $cookie.get("EcmaDoc.toggled");
	if (hidden)
	{
		hidden = hidden.split(",");
		for (var i = 0; i < hidden.length; i++)
		{
			var switchElem = $(".toggleblock.{0} .togglehead .switch".format(hidden[i]));
			EcmaDoc.Toggle.hideBlock(switchElem);
			EcmaDoc.Toggle.deleteRule();
		}

		EcmaDoc.Toggle.updateSwitches();
	}
};

EcmaDoc.Toggle.deleteRule = function Toggle$insertRule()
{
	var stylesheet = document.styleSheets[document.styleSheets.length - 1];
	if (stylesheet.removeRule)
	{
		stylesheet.removeRule(stylesheet.rules.length - 1);
	}
	else
	{
		stylesheet.deleteRule(stylesheet.cssRules.length - 1);
	}
};

EcmaDoc.Toggle.insertRule = function Toggle$insertRule(selector, style)
{
	var stylesheet = document.styleSheets[document.styleSheets.length - 1];
	if (stylesheet)
	{
		if (stylesheet.addRule)
		{
			stylesheet.addRule(selector, style);
		}
		else
		{
			stylesheet.insertRule(String.format("{0} {{1}}", selector, style), stylesheet.cssRules.length);
		}
	}
};

EcmaDoc.Toggle.preInitializeSwitches = new function Toggle$preInitializeSwitches()
{
	try
	{
		var hidden = $cookie.get("EcmaDoc.toggled");
		if (hidden)
		{
			var cssText = [];
			hidden = hidden.split(",");
			for (var i = 0; i < hidden.length; i++)
			{
				var selector = ".toggleblock.{0} .toggledetail".format(hidden[i]);
				EcmaDoc.Toggle.insertRule(selector, "display: none");
			}
		}
	}
	catch(e)
	{
		$log.error(e)
	}
};

$evt.addListener(window, "onload", EcmaDoc.Toggle.setup);
$evt.addListener(window, "onload", EcmaDoc.Toggle.initializeSwitches);

